#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

#include "gui/gui.h"

typedef struct RectViewData
{
    uint32_t rect_color;
} RectViewData;

static int RectViewDestroyData(RectViewData *data)
{
    if (!data)
        return -1;

    free(data);
    return 0;
}

int RectViewMeasure(RectView *rectView)
{
    if (!rectView || !rectView->viewdata)
        return -1;

    LayoutParams *rectParams = &rectView->params;

    if (rectParams->available_w <= 0 || rectParams->available_h <= 0)
    {
        rectView->measured_w = 0;
        rectView->measured_h = 0;
        return -1;
    }

    int layout_max_w = rectParams->available_w - rectParams->margin_left - rectParams->margin_right; // 最大宽度
    int layout_max_h = rectParams->available_h - rectParams->margin_top - rectParams->margin_bottom; // 最大高度
    int layout_wrap_w = rectView->padding_left + rectView->padding_right;                            // 包裹宽度
    int layout_wrap_h = rectView->padding_top + rectView->padding_bottom;                            // 包裹高度

    rectView->wrap_w = layout_wrap_w;
    rectView->wrap_h = layout_wrap_h;

    // 测量宽度（绘制时确定的宽度）
    if (rectParams->layout_w == TYPE_LAYOUT_SIZE_MATH_PARENT)
        rectView->measured_w = layout_max_w;
    else if (rectParams->layout_w == TYPE_LAYOUT_SIZE_WRAP_CONTENT)
        rectView->measured_w = layout_wrap_w;
    else
        rectView->measured_w = rectParams->layout_w;
    if (rectView->measured_w > layout_max_w)
        rectView->measured_w = layout_max_w;
    if (rectView->measured_w < 0)
        rectView->measured_w = 0;

    // 测量高度（绘制时确定的高度）
    if (rectParams->layout_h == TYPE_LAYOUT_SIZE_MATH_PARENT)
        rectView->measured_h = layout_max_h;
    else if (rectParams->layout_h == TYPE_LAYOUT_SIZE_WRAP_CONTENT)
        rectView->measured_h = layout_wrap_h;
    else
        rectView->measured_h = rectParams->layout_h;
    if (rectView->measured_h > layout_max_h)
        rectView->measured_h = layout_max_h;
    if (rectView->measured_h < 0)
        rectView->measured_h = 0;

    return 0;
}

int RectViewDraw(RectView *rectView)
{
    if (!rectView)
        return -1;

    RectViewData *rectData = (RectViewData *)rectView->viewdata;
    LayoutParams *rectParams = &rectView->params;

    if (rectView->measured_w <= 0 || rectView->measured_h <= 0)
        return 0;

    int layout_x = rectParams->layout_x + rectParams->margin_left;
    int layout_y = rectParams->layout_y + rectParams->margin_top;
    int layout_w = rectView->measured_w;
    int layout_h = rectView->measured_h;

    int content_x = layout_x + rectView->padding_left;
    int content_y = layout_y + rectView->padding_top;
    int content_w = layout_w - rectView->padding_left - rectView->padding_right;
    int content_h = layout_h - rectView->padding_top - rectView->padding_bottom;

    if (rectView->bg_color)
        GUI_DrawFillRectangle(layout_x, layout_y, layout_w, layout_h, rectView->bg_color);

    if (rectData->rect_color)
        GUI_DrawFillRectangle(content_x, content_y, content_w, content_h, rectData->rect_color);

    return 0;
}

int RectViewSetRectColor(RectView *rectView, uint32_t color)
{
    if (!rectView || !rectView->viewdata)
        return -1;

    RectViewData *rectData = (RectViewData *)rectView->viewdata;
    rectData->rect_color = color;

    return 0;
}

uint32_t RectViewGetRectColor(RectView *rectView)
{
    if (!rectView || !rectView->viewdata)
        return 0;

    RectViewData *rectData = (RectViewData *)rectView->viewdata;
    return rectData->rect_color;
}

int RectViewInit(RectView *rectView)
{
    if (!rectView)
        return -1;

    memset(rectView, 0, sizeof(RectView));

    rectView->viewdata = calloc(1, sizeof(RectViewData));
    if (!rectView->viewdata)
        return -1;

    rectView->onMeasure = RectViewMeasure;
    rectView->onDraw = RectViewDraw;
    rectView->onFinish = RectViewDestroy;

    return 0;
}

int RectViewDeinit(RectView *rectView)
{
    if (!rectView)
        return -1;

    RectViewDestroyData((RectViewData *)rectView->viewdata);
    memset(rectView, 0, sizeof(RectView));

    return 0;
}

RectView *NewRectView()
{
    RectView *rectView = (RectView *)malloc(sizeof(RectView));
    if (!rectView)
        return NULL;

    if (RectViewInit(rectView) < 0)
    {
        free(rectView);
        return NULL;
    }

    return rectView;
}

int RectViewDestroy(RectView *rectView)
{
    if (!rectView)
        return -1;

    if (rectView->dont_free)
        return 0;

    RectViewDestroyData((RectViewData *)rectView->viewdata);
    free(rectView);

    return 0;
}
